#include <string.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include "head.h"
#include <mysql/mysql.h>
//服务器
/*      在服务器中连接MySQL,查找对应路径下的文件名的哈希值,将哈希值作为文件名,
        打开文件发送,并发送给客户端*/
//服务器
/*      在服务器中连接MySQL,查找对应路径下的文件名的哈希值,将哈希值作为文件名,
        打开文件发送,并发送给客户端*/
int put_server(int netfd, MYSQL* my) {

    off_t token_len = 0;                                
    char token[1024] = {0};
    memset(token, 0, sizeof(token));
    recv(netfd, &token_len, sizeof(off_t), MSG_WAITALL);
    recv(netfd, token, token_len, MSG_WAITALL);
    printf("---------------------------\ntoken: %s\n", token);

    char token_tmp[1024] = {0};
    memset(token_tmp, 0, sizeof(token_tmp));
    free_JWT(token, token_tmp);

    int tmp_fd = atoi(strtok(token_tmp, "&"));
    char* user_id = strtok(NULL, "&");
    printf("user_id: %s\n", user_id);

    off_t path_len = 0;
    char path[1024] = {0};
    memset(path, 0, sizeof(path));
    recv(netfd, &path_len, sizeof(off_t), MSG_WAITALL);
    recv(netfd, path, path_len, MSG_WAITALL);
    printf("path: %s\n", path);

    char recvt[32 + sizeof(ssize_t)] = {0};
    int ret_recv = recv(netfd, recvt, sizeof(recvt), 0);
    ERROR_CHECK(ret_recv, -1, "error recv name");

    // WARNING: 文件名过长时候,小火车的文件名32上限需要修
    char name[32] = {0};
    ssize_t lseek_offset = 0;
    // 写入数据
    memcpy(name, recvt, 32);
    memcpy(&lseek_offset, recvt + 32, sizeof(ssize_t));
    printf("写入的文件名是%s", name);

    //=============================合并路径的======================================
    //char *paths = "/home/luguanbo/123/";     //最后应该要加一个/,否则后面拼接路径有问题
    //   /home/xsc/cloud_drive/new/project/serve
    char full_path[2048] = {0};
    // 将 paths, task->path连接,然后一写入full_path中
    snprintf(full_path, sizeof(full_path), "%s/%s", path, name);  //-->拼接可能有问题
                                                                  //char full_path1[1024] = {0};
                                                                  //snprintf(full_path1, sizeof(full_path), "%s%s", full_path, path);
                                                                  //=============================================================================



    printf("full_path:%s\n", full_path);	// 1024

    //  --->> 需要检查数据库中是否含有这个文件,就是删除标志是否为标志删除

    char formysql[4096] = {0};
    sprintf(formysql,"SELECT `hash2` FROM file where `delete` = '0' and `path` = '%s' and `user_id` = '%s'",full_path,user_id);

    if (mysql_query(my, formysql))
    {
        printf("%s\n",mysql_error(my));
        mysql_close(my);
        return EXIT_FAILURE;
    }
    //0是没删除 1删除

    //找到虚拟路径下的文件,需要将这个虚拟映射转化为服务器真实的文件
    //--->将MySQL中这个路径对应的文件路径找到,然后取出对应的哈希值发送给客户端

    MYSQL_RES *res = mysql_store_result(my);
    MYSQL_ROW row = mysql_fetch_row(res);

    int rows = mysql_num_rows(res);
    char sig1= '0';
    char sig2 = '1';
    //无文件发送信号'0',有文件发送'1'
    if(rows==0){
        send(netfd, &sig1, 1, 0);
        return 0;
    }else{
        send(netfd, &sig2, 1, 0);

    }

    //数据,
    //row[0] //-->hash2的值

    /* char realfile[1024] = {"/home/luguanbo/database"}; */
    char realfile[1024];
    bzero(realfile, sizeof(realfile));
    getparameter("realfile", realfile);
    strcat(realfile, "/");
    strcat(realfile, row[0]);
    printf("realfile:%s\n",realfile);

    int filefd = open(realfile, O_RDWR); // -->已经获取到真实文件


    char sha[41] = {0};		// 两个都多一个位专用于存储 \0
    char md[33] = {0};		// -->用刚刚已经拿到的路径直接计算文件哈希值,并存储

    char filepath[1024] = {0};
    memcpy(filepath, "sha1sum ", 8);
    memcpy(filepath + 8, realfile, sizeof(realfile) - 8); // -->将命令组合起来,修正偏移量

    FILE *fp = popen(filepath, "r"); 						// -->计算哈希值,然后读取此处是sha1的
    fread(sha, sizeof(char), sizeof(sha)-1, fp);				//sha1哈希读取完毕
    sha[40] = 0;
    memset(filepath, 0, sizeof(filepath));					// 清空路径;
    pclose(fp);												// 关闭管道
    memcpy(filepath, "md5sum ", 7);
    memcpy(filepath + 7, realfile, sizeof(realfile) - 7);
    fp = popen(filepath, "r");
    fread(md, sizeof(char), sizeof(md)-1, fp);
    md[32] = 0;
    // 强制将第33位修改为\0
    printf("文件哈希值是\nsha1 = %s \nmd5 = %s \n", sha, md);
    pclose(fp);
    //==============================================================================

    ERROR_CHECK(filefd, -1, "error open file");
    struct stat file;
    fstat(filefd, &file);
    ssize_t length = file.st_size - lseek_offset;

    char *_info =
        (char *)calloc(sizeof(ssize_t) + sizeof(sha) + sizeof(md), sizeof(char));
    memcpy(_info, &length, sizeof(ssize_t));
    memcpy(_info + sizeof(ssize_t), sha, sizeof(sha));
    memcpy(_info + sizeof(ssize_t) + sizeof(sha), md, sizeof(md));
    // 获取文件长度,sha1/md5哈希值,然后发送这些信息

    send(netfd, _info, sizeof(ssize_t)+41+33, 0);
    printf("%s\n",_info); 
    // 文件信息发送完毕,开始发送文件本体
    printf("发送到文件大小是:%ld\n", length);

    ssize_t sent = 0;
    while (sent < length) {
        ssize_t ret_send = sendfile(netfd, filefd, &lseek_offset, length - sent);
        ERROR_CHECK(ret_send, -1, "error sendfile");
        sent += ret_send;
    }
    printf("文件发送完毕\n");
    close(filefd);
    return 0;
}
